﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.Manager;
using System.Windows.Forms;

namespace SdmxMl.SanteSuisse
{
    public class QuestionBloc
    {
        #region Internal Members
        private SmManager _sm;

        private static string surveyYearsInfo = "1992 1997 2002 2007";
        private static string surveyListMark = "-------------------------------------";
        private int rowStartList;
        private int rowEndList;

        private DataTable _dtWorksheet;
        private int questionRow;

        private List<string> questionInfoList;
        private List<string> thematicList;
        private List<string> varsList;
        private List<string> varsListName;
        private Dictionary<string, string> dicoCodeList;
        private Dictionary<string, string> dicoCodeContinue;
        private Dictionary<string, string> dicoCodeQuality;

        #endregion //Internal Members

        #region properties

        public Dictionary<string, string> DicoCodeQuality
        {
            get { return dicoCodeQuality; }
        }

        public Dictionary<string, string> DicoCodeList
        {
            get { return dicoCodeList; }
        }

        public Dictionary<string, string> DicoCodeContinue
        {
            get { return dicoCodeContinue; }
        }

        public List<string> VarsList
        {
            get { return varsList; }
        }

        public List<string> VarsListName
        {
            get { return varsListName; }
        }

        public bool IsYesNo
        {
            get;
            set;
        }

        public int NextQuestionRow
        {
            get;
            set;
        }
        public string SurveyYears
        {
            get;
            set;
        }

        // Sometime before the question
        public string Usage
        {
            get;
            set;
        }

        public string Question
        {
            get;
            set;
        }
        public string Interviewer
        {
            get;
            set;
        }

        public string Module
        {
            get;
            set;
        }

        public string Theme
        {
            get;
            set;
        }
        // Question numbering
        public string No
        {
            get;
            set;
        }

        // Source / Remark
        public string Remark
        {
            get;
            set;
        }

        #endregion properties

        #region Construction

        private void Init(DataTable dtWorksheet)
        {
            _dtWorksheet = dtWorksheet;
            questionInfoList = new List<string>();
            thematicList = new List<string>();
            varsList = new List<string>();
            varsListName = new List<string>();
            dicoCodeList = new Dictionary<string, string>(16);
            dicoCodeContinue = new Dictionary<string, string>(16);
            dicoCodeQuality = new Dictionary<string, string>(16);
            rowStartList = rowEndList = 0;
            Remark = string.Empty;
        }

        public QuestionBloc(SmManager sm, int row, DataTable dtWorksheet)
        {
            Init(dtWorksheet);
            _sm = sm;

            // Read until end or next question Bloc
            ReadToNext(row);
        }
        public QuestionBloc(int row, DataTable dtWorksheet)
        {
            _sm = null;
            Init(dtWorksheet);

            // Read until end or next question Bloc
            ReadToNext(row);
        }

        #endregion //Construction

        private void UpdateRowList(int row)
        {
            if (GetCellContent(row, 1).StartsWith(surveyListMark))
            {
                if (rowStartList == 0)
                    rowStartList = row;
                else
                    rowEndList = row;
            }
        }

        private void UpdateRemark(string rowVal)
        {
            if (rowVal.Length > 0)
            {
                if (Remark.Length > 0)
                    Remark += Environment.NewLine;
                Remark += rowVal;
            }
        }
        private void UpdateVars(int row, string content)
        {
            string name = string.Empty;
            string[] arr = content.Split(' ');
            if (arr.Length == 1 && content.Length > 0 && content[0] == 'T' &&
                (content.Length == 7 || content.Length == 8))
            {

                // first 5 char must be uppercase
                for (int i = 0; i < 5; i++)
                    if (Char.IsLower(content[i]))
                        return;

                // If not yet variable, try to update Theme
                if (varsList.Count == 0)
                {
                    string up = GetCellContent(row - 1, 2);
                    if (up.Length > 0 && up != Theme)
                        Theme += " " + up;
                }

                // If a 8 digits make a parent to 7 if still nothing
                if (content.Length == 8)
                {
                    if (VarsList.Count == 0)
                    {
                        varsListName.Add(name);
                        varsList.Add(content.Substring(0, 7));
                    }
                    name = GetCellContent(row, 1);
                    
                }
                varsListName.Add(name);
                varsList.Add(content);
            }
        }

        private void UpdateQuestion(string content)
        {
            if (string.IsNullOrEmpty(Question))
                if (content.Length > 0)
                {
                    if (content.IndexOf('?') > 0)
                        Question = content;
                    else if (string.IsNullOrEmpty(Usage))
                        Usage = content;
                }
        }

        private void UpdateInt(string content)
        {
            if (string.IsNullOrEmpty(Interviewer))
                if (content.Length > 0 && content.IndexOf("INT:") >= 0)
                    Interviewer = content.Substring(4);
        }

        private void UpdateYears(int row)
        {
            StringBuilder sb = new StringBuilder(128);
            sb.Append(surveyYearsInfo).Append(Environment.NewLine);
            for (int col = 4; col < 8; col++)
            {
                string flg = GetCellContent(row, col);
                if (flg.Length > 3)
                    flg = flg.Substring(0, 3);
                sb.Append(' ').Append(flg);
                sb.Append(' ', 4 - flg.Length);
            }
            SurveyYears = sb.ToString();
        }


        private void ReadToNext(int row)
        {
            bool filled = false;
            // Ignore up to value in column NO
            if (GetNextNo(ref row))
            {
                questionRow = row;
                No = GetCellContent(row, 0);
                Theme = GetCellContent(row, 2);
                Module = GetCellContent(row, 3);
                UpdateYears(row);
                if (No == "47.20")
                {
                }
                do
                {
                    // fetch others cells
                    UpdateVars(row, GetCellContent(row, 2));
                    UpdateQuestion(GetCellContent(row, 1));
                    UpdateInt(GetCellContent(row, 1));
                    UpdateRowList(row);
                    UpdateRemark(GetCellContent(row, 8));

                    // Go to next row
                    ++row;
                    if (row >= _dtWorksheet.Rows.Count || GetCellContent(row, 0).Length > 0)
                    {
                        if (string.IsNullOrEmpty(Question))
                        {
                            Question = GetCellContent(questionRow, 1);
                            if (Question == Usage)
                               Usage = string.Empty;
                        }
                        if (rowStartList != 0 && rowEndList != 0)
                        {
                            /*
                            UpdateIsYesNo();
                            if (IsYesNo == false)
                            {
                            }
                             * */
                            FillCodelist();

                            FillCodeQuality();

                        }
                        filled = true;
                    }

                
                } while (!filled);
            }

            // Where to start with next questiion
            NextQuestionRow = row;
        }

        private bool GetNextNo(ref int row)
        {
            bool inFile = true;
            do
            {
                if (row < _dtWorksheet.Rows.Count)
                {
                    string s = GetCellContent(row, 0);
                    if (s.Length > 0 && s.Trim() != "No")
                        break; ;
                    ++row;
                }
                else
                {
                    inFile = false;
                    break;
                }
            } while (true);


            return inFile;
        }
  

        #region Helper

        /// <summary>
        /// Retrieve content of worksheet cell
        /// </summary>
        /// <param name="row">row index (from 1)</param>
        /// <param name="col">col index (from 1)</param>
        /// <returns>string cell content or empty string if nothing found</returns>
        public string GetCellContent(int row, int col)
        {
            return GetCellContent(row, col, string.Empty);
        }

        /// <summary>
        /// Retrieve content of worksheet cell
        /// </summary>
        /// <param name="row">row index (from 1)</param>
        /// <param name="col">col index (from 1)</param>
        /// <param name="dflt">default text if nothing found</param>
        /// <returns>string cell content or default if nothing found</returns>
        public string GetCellContent(int row, int col, string dflt)
        {
            string content = dflt;
                if (row < _dtWorksheet.Rows.Count && col < _dtWorksheet.Columns.Count)
                {
                    content = _dtWorksheet.Rows[row][col].ToString();
                    if (content == string.Empty)
                        content = dflt;
                }
                else
                    throw new ApplicationException(string.Format("Invalid cell location request {0}:{1}", row, col));

            return content.Trim();
        }
        #endregion //Helper

        #region Classifications

        private void UpdateIsYesNo()
        {
            string s = GetCellContent(rowStartList + 1, 1);
            if (s.StartsWith("- si 1") || s.StartsWith("- Yes 1") || s.StartsWith("- oui 1") || s.StartsWith("- ja 1"))
            {
                IsYesNo = true;
            }
        }
        private string ExtractCode(string s)
        {
            string code = string.Empty;
            string [] arr = s.Split(' ');
            if (arr.Length > 1)
            {
                code = arr[arr.Length - 1];
                // Some codes prepended by '.', remove.
                code = code.TrimStart('.');

                // Quality codes are under bracket
                code = code.Trim(new char[] { '(', ')' });
            }
            return code;
        }

        private void FillCodelist()
        {
            if (rowEndList - rowStartList > 2)
            {
                for (int index = rowStartList + 1; index < rowEndList; index++)
                {
                    string s = GetCellContent(index, 1);
                    string [] arr = s.Split(' ');
                    if (s.StartsWith("- ") && arr.Length > 1)
                    {
                        s = s.Substring(2);
                        s = RemoveContinueTo(s);
                        arr = s.Split(' ');
                        if (arr.Length > 1)
                        {
                            string code = ExtractCode(s);
                            StringBuilder sb = new StringBuilder();
                            for (int i = 0; i < arr.Length - 1; i++)
                                sb.Append(arr[i]).Append(' ');
                            string text = sb.ToString().TrimEnd();

                            if (dicoCodeList.ContainsKey(code) == false)
                                dicoCodeList.Add(code, text);
                            else
                            {
                                dicoCodeList.Clear();
                                break;
                            }
                        }

                    }
                    else
                    {
                        dicoCodeList.Clear();
                        break;
                    }
                }
            }
        }

        static string[] arrCont = { "suite ", "weiter zu ", "continue to ", "segue " };

        private string RemoveContinueTo(string rowCode)
        {
            string s = rowCode;
            string cont = string.Empty;
            int ndx = -1;
            for (int lg = 0; lg < arrCont.Length; lg++)
            {
                cont = arrCont[lg];
                ndx = rowCode.IndexOf(cont);
                if (ndx > 0)
                    break;
            }

            if (ndx > 0)
            {
                s = rowCode.Substring(0, ndx).Trim(' ');
                string code = ExtractCode(s);
                if (dicoCodeContinue.ContainsKey(code) == false)
                {
                    string no = rowCode.Substring(ndx);
                    no = no.Substring(cont.Length).Trim(' ');
                    string[] ar = no.Split(' ');
                    dicoCodeContinue.Add(code, ar[ar.Length-1]);
                }
            }

            return s;
        }
        #endregion

        #region Quality

        private void FillCodeQuality()
        {
            int row = rowEndList + 1;


            while (row < _dtWorksheet.Rows.Count && GetCellContent(row, 0).Length == 0)
            {
                string s = GetCellContent(row, 1);
                string[] arr = s.Split(' ');
                if (s.StartsWith("- ") && arr.Length > 1)
                {
                    s = s.Substring(2); // skip - 
                    s = RemoveContinueTo(s);
                    arr = s.Split(' ');
                    if (arr.Length > 1)
                    {
                        string code = ExtractCode(s);
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < arr.Length - 1; i++)
                            sb.Append(arr[i]).Append(' ');
                        string text = sb.ToString().TrimEnd();

                        if (dicoCodeQuality.ContainsKey(code) == false)
                            dicoCodeQuality.Add(code, text);
                        else
                        {
                            dicoCodeQuality.Clear();
                            break;
                        }
                    }
                }
                else
                    break;

                ++row;
            }

        }


        #endregion
    }

}
